/****************************************************************************************
**  File: Vector2.hpp
**  Author: Asteroth
**  Date: 22/02/2009
****************************************************************************************/

#ifndef __VECTOR2_HPP__
#define __VECTOR2_HPP__

template <class T>
class Vector2x
{
    public:
        T X, Y;

        // --- Constructors ----------------------------------------------------
        Vector2x();
        Vector2x( const Vector2x<T> &vect );
        Vector2x( T x, T y );

        // --- Operators -------------------------------------------------------
        // a = b
        inline Vector2x<T> &operator = ( const Vector2x<T> &set );
        // a += b   a -= b   a + b   a - b
        inline Vector2x<T> &operator += ( const Vector2x<T> &add );
        inline Vector2x<T> &operator -= ( const Vector2x<T> &sub );
        inline Vector2x<T> operator + ( const Vector2x<T> &add ) const;
        inline Vector2x<T> operator - ( const Vector2x<T> &sub ) const;
        inline Vector2x<T> operator - () const;
        // a *= scalar   a /= scalar   a * scalar   a / scalar
        inline Vector2x<T> &operator *= ( const T scalar );
        inline Vector2x<T> &operator /= ( const T scalar );
        inline Vector2x<T> operator * ( const T scalar ) const;
        inline Vector2x<T> operator / ( const T scalar ) const;
        // dot product: a || b
        inline T operator || ( const Vector2x<T> &dot ) const;
        // normal: !a
        inline Vector2x<T> operator ! () const;
        // length: ~a
        inline T operator ~ () const;
};

typedef Vector2x<float> Vector2;

const Vector2 INF_VECTOR2 = Vector2(INFINITY, INFINITY);
const Vector2 ZERO_VECTOR2 = Vector2(0.0f, 0.0f);

template <class T> Vector2x<T>::Vector2x()
    { X = (T)0.0; Y = (T)0.0; }
template <class T> Vector2x<T>::Vector2x( const Vector2x<T> &vect )
    { X = vect.X; Y = vect.Y; }
template <class T> Vector2x<T>::Vector2x( T x, T y )
    { X = x; Y = y; }

template <class T> inline Vector2x<T> &Vector2x<T>::operator = ( const Vector2x<T> &set )
    { X = set.X; Y = set.Y; return *this; }
template <class T> inline Vector2x<T> &Vector2x<T>::operator += ( const Vector2x<T> &add )
    { X += add.X; Y += add.Y; return *this; }
template <class T> inline Vector2x<T> &Vector2x<T>::operator -= ( const Vector2x<T> &sub )
    { X -= sub.X; Y -= sub.Y; return *this; }
template <class T> inline Vector2x<T> Vector2x<T>::operator + ( const Vector2x<T> &add ) const
    { return Vector2x<T>( X + add.X, Y + add.Y ); }
template <class T> inline Vector2x<T> Vector2x<T>::operator - ( const Vector2x<T> &sub ) const
    { return Vector2x<T>( X - sub.X, Y - sub.Y ); }
template <class T> inline Vector2x<T> Vector2x<T>::operator - () const
    { return Vector2x<T>( -X, -Y ); }
template <class T> inline Vector2x<T> &Vector2x<T>::operator *= ( const T scalar )
    { X *= scalar; Y *= scalar; return *this; }
template <class T> inline Vector2x<T> &Vector2x<T>::operator /= ( const T scalar )
    { X /= scalar; Y /= scalar; return *this; }
template <class T> inline Vector2x<T> Vector2x<T>::operator * ( const T scalar ) const
    { return Vector2x<T>( X * scalar, Y * scalar ); }
template <class T> inline Vector2x<T> Vector2x<T>::operator / ( const T scalar ) const
    { return Vector2x<T>( X / scalar, Y / scalar ); }
template <class T> inline T Vector2x<T>::operator || ( const Vector2x<T> &dot ) const
    { return X * dot.X + Y * dot.Y; }
template <class T> inline Vector2x<T> Vector2x<T>::operator ! () const
    { float len = sqrt( X * X + Y * Y );
    if ( len == 0 ) len = 1;
    return Vector2x<T>( X / len, Y / len ); }
template <class T> inline T Vector2x<T>::operator ~ () const
    { return sqrt( X * X + Y * Y ); }

#endif
